#ifndef LISTA_HPP_
#define LISTA_HPP_
#include "Lista.h"
#include <string.h>
#include <sstream>
#include <stdlib.h>

using namespace std;

template<class T>
Lista<T>::Lista(int t) {

	tamanho = 0 < t ? t : 100;

	Inicializa();
	dados = (T*) malloc(sizeof(T) * t);
}

template<class T>
int Lista<T>::Adiciona(T elemento) {

	if (EstaCheia()) {
		throw ERROLISTACHEIA;
	} else {

		dados[++ultimo] = elemento;
	}
	return ultimo;
}

template<class T>
T Lista<T>::Retira() {
	if (EstaVazia()) {
		throw ERROLISTAVAZIA;
	} else {

		return dados[ultimo--];
	}
}
template<class T>
T Lista<T>::RetiraDoInicio() {
	if (EstaVazia()) {
		throw ERROLISTAVAZIA;
	} else {
		int i;
		--ultimo;
		T valor = dados[0];
		for (i = 0; i < ultimo + 1; i++) {
			dados[i] = dados[i + 1];
		}
		return valor;
	}

}
template<class T>
inline void Lista<T>::Limpar() {
	ultimo = -1;
}

template<class T>
Lista<T>::~Lista() {

	free(dados);

}

template<class T>
int Lista<T>::AdicionaNoInicio(T elemento) {
	if (EstaCheia()) {
		throw ERROLISTAVAZIA;
	} else {
		++ultimo;
		int pos = ultimo;
		while (pos > 0) {
			dados[pos] = dados[pos - 1];
			pos -= 1;
		}
		dados[0] = elemento;
	}

	return 0;
}

template<class T>
int Lista<T>::AdicionaNaPosicao(T elemento, int posicao) {
	if (posicao < 0 || posicao > tamanho - 1) {
		throw ERROPOSICAO;
	} else if (EstaCheia()) {
		throw ERROLISTACHEIA;

	} else {
		++ultimo;
		int contador = ultimo;
		while (contador > posicao) {
			dados[contador] = dados[contador - 1];
			contador -= 1;
		}
		dados[posicao] = elemento;
	}
	return posicao;
}

template<class T>
int Lista<T>::AdicionaEmOrdem(T elemento) {

	if (EstaVazia()) {
		return AdicionaNoInicio(elemento);
	} else {
		int contador = 0;

		while (elemento > dados[contador] && ultimo > contador) {

			contador++;
		}

		return AdicionaNaPosicao(elemento, contador);

	}

}

template<class T>
T Lista<T>::RetiraDaPosicao(int posicao) {
	if (EstaVazia()) {
		throw ERROLISTAVAZIA;
	}

	if (posicao < 0 || posicao > ultimo) {
		throw ERROPOSICAO;
	}

	T aux = dados[posicao];
	--ultimo;
	int contador = ultimo;
	while (contador >= posicao) {
		dados[posicao] = dados[posicao + 1];
		contador -= 1;
	}

	return aux;

}

template<class T>
T Lista<T>::RetiraEspecifico(T elemento) {

	return RetiraDaPosicao(PosicaoDoElemento(elemento));

}

template<class T>
int Lista<T>::ObtemUltimo() {
	return ultimo;
}

template<class T>
T Lista<T>::ObtemElemento(int pos) {
	return dados[pos];
}

template<class T>
inline void Lista<T>::Inicializa() {
	ultimo = -1;

}

template<class T>
bool Lista<T>::EstaCheia() {
	return ultimo == tamanho - 1;

}
template<class T>
bool Lista<T>::EstaVazia() {
	return ultimo == -1;
}

template<class T>
int Lista<T>::PosicaoDoElemento(T elemento) {
	int pos = 0;

	while (pos <= ultimo && !(elemento == dados[pos])) {
		pos++;
	}
	return pos;
}
#endif
